class LightTip extends HTMLElement {
  // 返回一个数组，包含需要观察的属性
  static get observedAttributes() {
    return ["open"];
  }

  constructor() {
    // 调用父类的构造函数
    super();

    // 如果有参数传入，则调用LightTip.custom方法
    if (arguments.length) {
      LightTip.custom.apply(this, arguments);
    }
  }

  // 获取type属性
  get type() {
    return this.getAttribute("type");
  }
  // 设置type属性
  set type(value) {
    this.setAttribute("type", value);
  }

  // 获取time属性
  get time() {
    // 获取time属性的值
    let strTime = this.getAttribute("time");
    // 判断strTime是否为数字
    if (!isNaN(strTime) && !isNaN(parseInt(strTime))) {
      // 如果是数字，则返回parseInt(strTime)
      return parseInt(strTime);
    }
    // 如果不是数字，则返回3000
    return 3000;
  }
  // 设置time属性
  set time(value) {
    // 设置time属性的值为value
    this.setAttribute("time", value);
  }

  // 获取open属性
  get open() {
    return this.hasAttribute("open");
  }
  // 设置open属性
  set open(value) {
    this.toggleAttribute("open", value);
  }

  // 当元素被连接到DOM时调用
  connectedCallback() {
    // 设置元素的tabIndex属性为0，使其可聚焦
    this.setAttribute("tabIndex", 0);
    // 设置元素的role属性为tooltip，使其具有提示框的角色
    this.setAttribute("role", "tooltip");

    // 如果closeMode属性不存在，则将其设置为"hide"
    if (!this.closeMode) {
      this.closeMode = "hide";
    }

    // 添加点击事件监听器，当元素被点击时，调用closeMode属性对应的函数
    this.addEventListener("click", () => {
      this[this.closeMode]();
    });

    // 触发自定义事件"connected"，传递detail属性，其中包含type属性为"ui-lightTip"
    this.dispatchEvent(
      new CustomEvent("connected", {
        detail: {
          type: "ui-lighttip",
        },
      })
    );

    // 设置isConnectedCallback属性为true，表示元素已经被连接到DOM
    this.isConnectedCallback = true;
  }

  attributeChangedCallback(name, oldValue, newValue) {
    // 如果属性名是open，并且新旧值类型不同
    if (name == "open" && typeof oldValue !== typeof newValue) {
      // 如果新值是字符串类型
      if (typeof newValue === "string") {
        // 如果timer存在，清除定时器
        this.timer && clearTimeout(this.timer);
        // 设置定时器，在time时间后执行
        this.timer = setTimeout(() => {
          // 设置isTimeHide为true
          this.isTimeHide = true;
          // 执行closeMode方法
          this[this.closeMode]();
          // 调用position方法
          this.position();
        }, this.time);

        // 设置data-tid属性为timer
        this.setAttribute("data-tid", this.timer);
        // 添加ESC类
        this.classList.add("ESC");
        // 调用zIndex方法
        this.zIndex();
        // 调用position方法
        this.position();
      } else {
        // 移除ESC类
        this.classList.remove("ESC");
      }
      // 调用tabIndex方法
      this.tabIndex();
      // 设置isTimeHide为null
      this.isTimeHide = null;
    }
  }

  // 获取元素的z-index值
  zIndex() {
    // 初始化z-index值为19
    let numZIndexNew = 19;
    // 判断父元素是否存在
    this.parentElement &&
      // 遍历父元素的子元素
      [...this.parentElement.childNodes].forEach((item) => {
        // 判断子元素的节点类型是否为元素节点
        if (item.nodeType != 1) {
          return;
        }
        // 获取子元素的样式
        const objStyleChild = getComputedStyle(item);
        // 获取子元素的z-index值
        const index = objStyleChild.zIndex * 1;
        // 判断子元素的z-index值是否存在且display属性不为none
        if (index && objStyleChild.display != "none") {
          // 更新z-index值为子元素的z-index值加1和当前z-index值中的较大值
          numZIndexNew = Math.max(index + 1, numZIndexNew);
        }
      });
    // 设置元素的z-index值为更新后的z-index值
    this.style.zIndex = numZIndexNew;
  }

  // 获取所有打开的ui-lighttip元素，不包括type为loading的元素
  position() {
    const elesOpen = [
      ...document.querySelectorAll("ui-lighttip[open]:not([type='loading'])"),
    ];
    // 将打开的ui-lighttip元素按照data-tid属性进行排序
    const elesOpenSort = elesOpen.sort(
      (a, b) =>
        (a.getAttribute("data-tid") || 0) - (b.getAttribute("data-tid") || 0)
    );
    // 创建一个对象，用于存储每个文本内容的索引
    const objMatchText = {};
    // 初始化索引为-1
    let numIndex = -1;

    // 遍历排序后的ui-lighttip元素
    elesOpenSort.forEach((ele) => {
      // 获取元素的文本内容
      let strText = ele.textContent;
      // 如果objMatchText对象中不存在该文本内容，则将索引加1，并将该文本内容添加到objMatchText对象中
      if (typeof objMatchText[strText] == "undefined") {
        numIndex++;
        objMatchText[strText] = numIndex;
      }
      // 将索引值设置为元素的--ui-sort-index属性
      ele.style.setProperty("--ui-sort-index", objMatchText[strText]);
    });
  }

  // 设置tabIndex
  tabIndex() {
    // 获取当前元素
    const eleContainer = this;
    // 获取上一次激活的元素
    const eleLastActive = LightTip.lastActiveElement;
    // 如果当前元素是打开状态
    if (this.open == true) {
      // 获取当前激活的元素
      const eleActiveElement = document.activeElement;
      // 如果当前激活的元素存在且不是[keepfocus]元素
      if (eleActiveElement && !eleActiveElement.closest("[keepfocus]")) {
        // 如果当前元素不是当前激活的元素
        if (eleContainer != eleActiveElement) {
          // 将当前激活的元素保存为上一次激活的元素
          LightTip.lastActiveElement = eleActiveElement;
        }
        // 将当前元素设置为激活状态
        eleContainer.focus();
      }
      // 如果当前元素是关闭状态
    } else if (eleLastActive && !eleLastActive.matches("body")) {
      // 将上一次激活的元素设置为激活状态
      eleLastActive.focus({ preventScroll: true });
      // 如果不是键盘事件且不是定时隐藏
      if (!window.isKeyEvent && !this.isTimeHide) {
        // 将上一次激活的元素设置为非激活状态
        eleLastActive.blur();
      }
      // 将上一次激活的元素设置为null
      LightTip.lastActiveElement = null;
    }
    // 返回当前元素
    return this;
  }

  // 静态方法，用于显示成功提示信息
  static success(text, time = 3000) {
    // 调用custom方法，传入text、"success"和time参数，返回结果
    return this.custom(text, "success", time);
  }

  // 静态方法，用于显示错误信息
  static error(text, time = 3000) {
    // 调用custom方法，传入text、"error"和time参数，返回custom方法的返回值
    return this.custom(text, "error", time);
  }

  // 静态方法，用于显示普通提示信
  static normal(text, time = 3000) {
    // 调用custom方法，传入text、"normal"和time参数，返回custom方法的返回值
    return this.custom(text, "normal", time);
  }

  // 静态方法，用于显示加载中的提示
  static loading(text) {
    // 如果没有传入参数，则默认显示"正在加载中..."
    text = text || "正在加载中...";
    // 调用custom方法，传入参数text、"loading"和0
    return this.custom(text, "loading", 0);
  }

  // 静态方法，用于创建自定义的LightTip
  static custom(text = "", type, time) {
    // 如果没有匹配到ui-lighttip，则使用LightTip的custom方法创建
    if (!this.matches || !this.matches("ui-lighttip")) {
      return LightTip.custom.apply(
        document.createElement("ui-lighttip"),
        arguments
      );
    }
    // 如果text是对象，则将type赋值为text，text赋值为空字符串
    if (typeof text == "object") {
      type = text;
      text = "";
    }
    // 如果text不是字符串，则返回this
    if (typeof text != "string") {
      return this;
    }
    // 设置关闭模式为remove
    this.closeMode = "remove";
    // 如果type是对象，则调用LightTip的custom方法
    if (type && typeof type == "object") {
      LightTip.custom.call(this, text, type.type, type.time);
      return;
    }
    // 如果type是数字，则调用LightTip的custom方法
    if (typeof type == "number") {
      LightTip.custom.call(this, text, time, type);
      return;
    }
    // 如果type是loading，则设置text为"正在加载中..."，time为999999
    if (type == "loading") {
      if (!text) {
        text = "正在加载中...";
      }
      time = 999999;
    }
    // 如果time存在，则设置this的time属性为time
    if (time) {
      this.time = time;
    }
    // 如果type存在，则设置this的type属性为type
    if (type) {
      this.type = type;
    }
    // 设置this的innerHTML为text
    this.innerHTML = text;
    // 如果type是success，则设置aria-lable为"操作成功"
    if (type == "success") {
      this.setAttribute("aria-lable", "操作成功");
    } else if (type == "error") {
      // 如果type是error，则设置aria-lable为"操作失败"
      this.setAttribute("aria-lable", "操作失败");
    }
    // 如果this没有父元素，则将其添加到body中，并触发DOMContentLoaded事件
    if (!this.parentElement) {
      document.body.appendChild(this);
      this.dispatchEvent(new CustomEvent("DOMContentLoaded"));
    }
    // 显示this
    this.show();
    // 返回this
    return this;
  }

  // 移除元素
  remove() {
    // 如果元素有父元素
    if (this.parentElement) {
      // 从父元素中移除该元素
      this.parentElement.removeChild(this);
    }
    // 将元素的open属性设置为false
    this.open = false;
  }

  // 显示函数
  show() {
    // 如果时间大于0
    if (this.time > 0) {
      // 打开
      this.open = true;
    }
  }

  // 隐藏函数
  hide() {
    // 将open属性设置为false，表示隐藏
    this.open = false;
  }
}

if (!customElements.get("ui-lighttip")) {
  customElements.define("ui-lighttip", LightTip);
}

window.LightTip = LightTip;

export default LightTip;
